package com.ruijie.acl.web;

import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.annotations.Transactional;

import com.ruijie.acl.AccessGroup;
import com.ruijie.acl.Ace;
import com.ruijie.acl.Template;
import com.ruijie.acl.Variable;
import com.ruijie.acl.service.AccessGroupService;
import com.ruijie.acl.service.AceService;
import com.ruijie.acl.service.TemplateService;
import com.ruijie.acl.type.WriteRuleTypeEnum;
import com.ruijie.acl.utils.AclUtil;
import com.ruijie.foundation.bo.EntityObject;
import com.ruijie.foundation.exception.BusinessException;
import com.ruijie.foundation.service.Repository;
import com.ruijie.foundation.utils.StringUtils;
import com.ruijie.foundation.web.intercept.AddSuccessInfo;

/**
 * <p>
 * Title: ACL模板管理Action类
 * </p>
 * <p>
 * Description:
 * </p>
 * <p>
 * 为ACL模板管理模块提供页面数据的显示、获取和页面的跳转。
 * </p>
 * <p>
 * Copyright: Copyright (c) 2008
 * </p>
 * <p>
 * Company: Ruijie Co., Ltd.
 * </p>
 * <p>
 * Create Time:
 * </p>
 * <p>
 * </p>
 * <p>
 * Update Time:
 * </p>
 * <p>
 * Updater:
 * </p>
 * <p>
 * Update Comments:
 * </p>
 * 
 * @author ASAI
 */

@Name("templateAction")
@Scope(ScopeType.CONVERSATION)
@AddSuccessInfo
public class TemplateAction extends AclBaseAction {

	@In("#{templateService}")
	private TemplateService templateService;
	@In("#{accessGroupService}")
	private AccessGroupService accessGroupService;
	@In("#{aceService}")
	private AceService aceService;

	private static Pattern pattern = Pattern.compile("\\$\\{[a-zA-Z0-9_]+\\}");

	/**
	 * 模板导出的ACL组名称
	 */
	private String accessGroupName;
	private Template criteria = new Template();
	private Template model;

	@Override
	@SuppressWarnings("unchecked")
	protected Repository getRepository() {
		return this.templateService;
	}

	@Override
	protected String getAddPage() {
		return "/acl/aclTemplate/templateAdd.seam";
	}

	@Override
	protected String getDetailPage() {
		return "/acl/aclTemplate/templateDetail.seam";
	}

	@Override
	protected String getListPage() {
		return "/acl/templateIndex.seam";
	}

	@Override
	protected String getUpdatePage() {
		return "/acl/aclTemplate/templateEdit.seam";
	}

	/**
	 * 导出页面的url
	 * 
	 * @return
	 */
	public String getExportPage() {
		return "/acl/aclTemplate/templateExport.seam";
	}

	/**
	 * 跳转到导出页面
	 * 
	 * @return
	 */
	public String toExportPage() {
		this.accessGroupName = "";
		return this.getExportPage();
	}

	@Override
	public EntityObject getModel() {
		return this.model;
	}

	@Override
	public EntityObject getCriteria() {
		return this.criteria;
	}

	@Override
	public void resetModel() {
		model = null;
		model = new Template();
	}

	@Override
	public void setCriteria(EntityObject criteria) {
		this.criteria = (Template) criteria;
	}

	@Override
	public void setModel(EntityObject model) {
		this.model = (Template) model;
	}

	@Override
	@Transactional
	protected boolean doAdd() {
		// 如果存在重名
		if (this.templateService.isExistsTemplateName(this.model.getName(),
				null)) {
			throw new BusinessException(
					"acl_template_validation_templateNameExisted");
		}
		this.templateService.save(this.model);
		return true;
	}

	@Override
	@Transactional
	protected boolean doUpdate() {
		// 如果存在重名
		if (this.templateService.isExistsTemplateName(this.model.getName(),
				this.model.getId())) {
			throw new BusinessException(
					"acl_template_validation_templateNameExisted");
		}
		this.templateService.update(this.model);
		return true;
	}

	/**
	 * 导出模板
	 * 
	 * @throws IllegalAccessException
	 * @throws IllegalArgumentException
	 */
	public String doExport() throws IllegalArgumentException,
			IllegalAccessException {

		// 如果存在相同的ACL组名称，则报错。
		if (accessGroupService.isExistGroupName(this.accessGroupName, null)) {
			//acl_validator_group_name=组名称已经存在
			throw new BusinessException("acl_validator_group_name");
		}

		Set<Variable> vars = this.model.getVariables();

		AccessGroup accessGroup = new AccessGroup();
		accessGroup.setName(this.accessGroupName);
		List<Ace> aces = this.aceService.getByTemplate(this.model);
		List<Ace> newAces = new ArrayList<Ace>();

		Field[] fields = Ace.class.getDeclaredFields();
		AccessibleObject.setAccessible(fields, true);
		for (Ace oldAce : aces) {
			Ace ace = new Ace();
			ace.setAccessGroup(accessGroup);
			ace.setTimeRange(oldAce.getTimeRange());
			boolean ignore = false;
			for (Field field : fields) {
				if (field.getType() == String.class
						|| field.getType() == Integer.class) {
					Object oldValue = field.get(oldAce);
					Object newValue = null;
					try {
						newValue = convert(oldValue, vars);
						if (newValue != null) {
							field.set(ace,
									(field.getType() == String.class ? newValue
											.toString() : Integer
											.parseInt(newValue.toString())));
						} else {
							field.set(ace, null);
						}
					} catch (Exception e) {
						// 未输入时忽略acl规则
						ignore = true;
						addGlobalI18nMessage("acl_template_ace_export_ignore",
								ace.getAceNum());
						break;
					}
				}
			}
			if (!ignore) {
				// 保存生成的acl规则
				// this.aceService.save(ace);
				AclUtil.filterAce(ace, this.model.getAccessGroupType());
				String validateResult = AclUtil.validateAce(ace, this.model
						.getAccessGroupType());
				if (validateResult == null || validateResult.length() == 0) {
					newAces.add(ace);
				} else {
					// 规则验证失败，不进行导出
					//acl_template_ace_export_failed=警告：{0}号规则导出失败！{1}
					String reason = this.getI18NMessage(validateResult);
					addGlobalI18nMessage("acl_template_ace_export_failed", ace
							.getAceNum(), reason);
					//acl_template_export_failed=模板导出失败!
					addGlobalI18nMessage("acl_template_export_failed");
					return this.getDetailPage();
				}
			}
		}
		accessGroup.setAces(null);
		accessGroup.setAclType(this.model.getAccessGroupType());

		try {
			accessGroupService.save(accessGroup);
			for (Ace ace : newAces) {
				Ace tempAce = ace.clone(accessGroup);
				tempAce.setAceNum(0);
				this.aceService.save(tempAce);
			}
			//acl_template_export_success=成功导出{0}条规则到ACL组：{1}
			addGlobalI18nMessage("acl_template_export_success", newAces.size(),
					accessGroupName);
		} catch (Exception e) {
			addGlobalI18nMessage("acl_template_export_failed");
			//e.printStackTrace();
		}

		return this.getDetailPage();
	}

	/**
	 * . 变量的替换操作
	 * 
	 * 
	 * 
	 * @param obj
	 * @return
	 * @throws Exception
	 *             未输入时忽略ACL规则，将抛出异常，以便让调用者捕捉并执行忽略操作
	 */
	public Object convert(Object obj, Set<Variable> vars) throws Exception {
		if (obj == null)
			return null;
		String input = obj.toString();
		StringBuffer output = new StringBuffer();
		Matcher matcher = pattern.matcher(input);
		int preStart = -1;
		int preEnd = 0;
		while (matcher.find()) {
			int start = matcher.start();
			int end = matcher.end();

			if (preStart < 0) {
				output.append(input.substring(0, start));
			} else {
				output.append(input.substring(preEnd, start));
			}

			String varName = input.substring(start + 2, end - 1);
			boolean replaceFlag = false;
			for (Variable var : vars) {
				if (varName.equals(var.getName())) {
					// 进行变量值的替换操作
					if (WriteRuleTypeEnum.noWrite.toString().equals(var.getFilledRule())
							&& StringUtils.isNullOrEmpty(var.getValue())) {
						// 未输入时忽略ACL规则
						throw new Exception("no value and ignore acl");
					}
					output.append(var.getValue());
					replaceFlag = true;
					break;
				}
			}
			if (!replaceFlag) {
				// 查找到${..}但是没有相应的变量进行替换，此时不进行替换,增加警告信息
				String temp = input.substring(start, end);
				addGlobalI18nMessage("acl_template_export_warning", varName);
				output.append(temp);
			}
			preStart = start;
			preEnd = end;
		}
		output.append(input.substring(preEnd));
		return output.toString();
	}

	public String getAccessGroupName() {
		return this.accessGroupName;
	}

	public void setAccessGroupName(String accessGroupName) {
		this.accessGroupName = accessGroupName;
	}
	
	
	//-------------modify by sinyee 2010-10-22 being----------------

	public String toAddPageBlank(){
		this.toAddPage();
		return null;
	}
	
	@AddSuccessInfo
	public String addEntity(){
		this.add();
		return null;
	}

	public String toUpdatePageBlank(EntityObject model,String previousPage){
		this.toUpdatePage(model, previousPage);
		return null;
	}
	
	@AddSuccessInfo
	public String updateEntity(){
		this.update();
		return null;
	}
	
	//--------------modify by sinyee 2010-10-22 end----------------
	

}
